package com.zbkj.crmeb.upload.service.impl;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.time.LocalDate;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.constants.Constants;
import com.utils.DateUtil;
import com.utils.OSSUtil;
import com.utils.UploadUtil;
import com.zbkj.crmeb.enums.ProductImageEnum;
import com.zbkj.crmeb.image.model.ProductImage;
import com.zbkj.crmeb.image.service.ProductImageService;
import com.zbkj.crmeb.system.service.SystemAttachmentService;
import com.zbkj.crmeb.system.service.SystemConfigService;
import com.zbkj.crmeb.upload.service.UploadService;
import com.zbkj.crmeb.upload.vo.FileResultVo;

import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;


/**
 * @author Mr.Zhang
 * @Description UploadServiceImpl 接口实现
 * @since 2020-05-06
 */
@Service
@Slf4j
public class UploadServiceImpl implements UploadService {
    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private SystemAttachmentService systemAttachmentService;

    @Autowired
    private ProductImageService productImageService;

    /**
     * 图片上传
     *
     * @param multipart MultipartFile 上传文件流
     * @param model     String 上传模块
     * @author Mr.Zhang
     * @since 2020-05-06
     */
    @Override
    public FileResultVo image(MultipartFile multipart, String model, Integer pid) throws IOException {
        setImageUpload(model);
        FileResultVo file = UploadUtil.file(multipart);
        //文件入库
        file.setType(file.getType().replace("image/", ""));
        systemAttachmentService.create(file, pid);
        return file;
    }

    /**
     * 图片上传OSS
     *
     * @param multipart MultipartFile 上传文件流
     * @param model     String 上传模块
     * @author Mr.Zhang
     * @since 2020-05-06
     */
    @Override
    public FileResultVo ossImage(MultipartFile multipart, String model, Integer pid, Integer merId) {
        FileResultVo file = null;
        try {
            setImageUpload(model);
            file = UploadUtil.uploadOssImage(multipart);
            //文件入库
            file.setType(file.getType().replace("image/", ""));
            file.setMerId(merId);
            systemAttachmentService.create(file, pid);
        } catch (Exception e) {
        	log.error("上传图片异常: ", e);
        }
        return file;
    }

    /**
     * 图片上传OSS
     *
     * @param multipart MultipartFile 上传文件流
     * @param model     String 上传模块
     * @author Mr.Zhang
     * @since 2020-05-06
     */
    @Override
    public FileResultVo imageV2(MultipartFile multipart, String model, Integer pid) {
        FileResultVo file = null;
        try {
            setImageUpload(model);
            file = UploadUtil.uploadOssImage(multipart);
            //文件入库
            file.setType(file.getType().replace("image/", ""));
            systemAttachmentService.create(file, pid);
        } catch (Exception e) {
            log.error("上传图片异常: ", e);
        }
        return file;
    }

    /**
     * 小视频
     */
    @Override
    public FileResultVo ossVideo(MultipartFile multipart, String model, Integer pid) {
    	FileResultVo file = null;
    	try {
    		setVideoUpload(model);
    		file = UploadUtil.uploadOssVideo(multipart);
    		//文件入库
//    		file.setType(file.getType().replace("image/", ""));
    		systemAttachmentService.create(file, pid);
    	} catch (Exception e) {
        	log.error("上传视频异常: ", e);
    	}
    	return file;
    }

    /**
     * 图片文件
     *
     * @param multipart MultipartFile 上传文件流
     * @param model     String 上传模块
     * @author Mr.Zhang
     * @since 2020-05-06
     */
    @Override
    public FileResultVo file(MultipartFile multipart, String model, Integer pid) throws IOException {
        setFileUpload(model);
        FileResultVo file = UploadUtil.file(multipart);

        //文件入库
        file.setType(file.getType().replace("file/", ""));
        systemAttachmentService.create(file, pid);
        return file;
    }

    /**
     * 设置上传图片参数
     *
     * @param model String 上传模块
     * @author Mr.Zhang
     * @since 2020-05-06
     */
    private void setImageUpload(String model) {
        UploadUtil.setRootPath(systemConfigService.getValueByKey(Constants.UPLOAD_ROOT_PATH_CONFIG_KEY));
        UploadUtil.setModelPath(model);
        UploadUtil.setExtStr(systemConfigService.getValueByKey(Constants.UPLOAD_IMAGE_EXT_STR_CONFIG_KEY));
        UploadUtil.setSize(Integer.parseInt(systemConfigService.getValueByKey(Constants.UPLOAD_IMAGE_MAX_SIZE_CONFIG_KEY)));
        UploadUtil.setType(Constants.UPLOAD_TYPE_IMAGE);
    }
    
    /**
     * 设置上传视频参数
     *
     * @param model String 上传模块
     * @author Mr.Zhang
     * @since 2020-05-06
     */
    private void setVideoUpload(String model) {
    	UploadUtil.setRootPath(systemConfigService.getValueByKey(Constants.UPLOAD_ROOT_PATH_CONFIG_KEY));
    	UploadUtil.setModelPath(model);
    	UploadUtil.setExtStr(systemConfigService.getValueByKey(Constants.UPLOAD_VIDEO_EXT_STR_CONFIG_KEY));
    	UploadUtil.setSize(Integer.parseInt(systemConfigService.getValueByKey(Constants.UPLOAD_VIDEO_MAX_SIZE_CONFIG_KEY)));
    	UploadUtil.setType(Constants.UPLOAD_TYPE_VIDEO);
    }

    /**
     * 设置上传文件参数
     *
     * @param model String 上传模块
     * @author Mr.Zhang
     * @since 2020-05-06
     */
    private void setFileUpload(String model) {
        UploadUtil.setRootPath(systemConfigService.getValueByKey(Constants.UPLOAD_ROOT_PATH_CONFIG_KEY));
        UploadUtil.setModelPath(model);
        UploadUtil.setExtStr(systemConfigService.getValueByKey(Constants.UPLOAD_FILE_EXT_STR_CONFIG_KEY));
        UploadUtil.setSize(Integer.parseInt(systemConfigService.getValueByKey(Constants.UPLOAD_FILE_MAX_SIZE_CONFIG_KEY)));
        UploadUtil.setType(Constants.UPLOAD_TYPE_FILE);
    }

//    @Override
//    public String zipImage(MultipartFile[] files) {
//        if (files == null || files.length == 0) {
//            log.info("-------------------上传文件为空!-----------------------");
//            return "上传文件为空!";
//        }
//        int count = 0;
//        StringBuilder str = new StringBuilder();
//        for (MultipartFile file : files) {
//            try {
//                //原文件名
//                String originalName = file.getOriginalFilename();
//                log.info("---------------文件名:{}--------------------", originalName);
//                if(StringUtils.isBlank(originalName)){
//                    log.info("---------------文件名不能为空串--------------------");
//                    str.append(originalName).append(";");
//                    continue;
//                }
//                originalName = originalName.contains("/") ? originalName.substring(originalName.lastIndexOf("/") + 1) : originalName;
//                //处理后文件名
//                String filename = handleName(originalName);
//                String color = getColor(str, originalName, filename);
//                if (color == null) continue;
//                String folder = filename.substring(0, filename.indexOf("~"));
//                String sort = filename.substring(filename.indexOf("(") + 1, filename.indexOf(")"));
//                //上传oss
//                OSSUtil.uploadLocalImage(Constants.UPLOAD_FILE_WAREHOUSE_DIR + folder + "/", file, filename);
//                ProductImage productImage = new ProductImage();
//                productImage.setFolderName(folder)
//                        .setColor(color)
//                        .setSort(sort)
//                        .setUrl(Constants.UPLOAD_FILE_WAREHOUSE_DIR + folder + "/" + filename);
//                count++;
//                productImageService.saveOrUpdate(productImage);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//        return "上传文件总数:" + files.length + ",上传成功:" + count + "条;"+ (StringUtils.isBlank(str) ? "" : "失败文件名称:"+str.toString());
//    }

//    @Override
//    public String uploadFolder(String path) {
//        if (path == null || "".equals(path.trim())) {
//            return "路径不能为空";
//        }
//        File file = new File(path);
//        File[] fileList = file.listFiles();
//        if(fileList == null || fileList.length<1){
//            return "文件夹为空";
//        }
//        int count = 0;
//        StringBuilder str = new StringBuilder();
//        for (File f : fileList) {
//            try {
//                String originalName = f.getName();
//                if (f.isDirectory()) {
//                    str.append(originalName).append(";");
//                    log.info("---------------跳过文件夹--------------------");
//                    continue;
//                }
//                log.info("---------------文件名:{}--------------------", originalName);
//                originalName = originalName.contains("/") ? originalName.substring(originalName.lastIndexOf("/") + 1) : originalName;
//                if (originalName.contains("/")) {
//                    originalName = originalName.substring(originalName.lastIndexOf("/") + 1);
//                }
//                String filename = handleName(originalName);
//                String color = getColor(str, originalName, filename);
//                if (color == null) continue;
//                String folder = filename.substring(0, filename.indexOf("~"));
//                String sort = filename.substring(filename.indexOf("(") + 1, filename.indexOf(")"));
//                //上传oss
//                OSSUtil.uploadLocalImage(Constants.UPLOAD_FILE_WAREHOUSE_DIR + folder + "/", f, filename);
//                ProductImage productImage = new ProductImage();
//                productImage.setFolderName(folder)
//                        .setColor(color)
//                        .setSort(sort)
//                        .setUrl(Constants.UPLOAD_FILE_WAREHOUSE_DIR + folder + "/" + filename);
//                count++;
//                productImageService.saveOrUpdate(productImage);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//        return "上传文件总数:" + fileList.length + ",上传成功:" + count + "条;" + (StringUtils.isBlank(str) ? "" : "失败文件名称:"+str.toString());
//    }
public static void main(String[] args) {
    File file = new File("D:\\WorkSpace\\SuYunNew\\crmeb-server\\src\\main\\java\\com\\zbkj\\crmeb\\merchant\\admin\\controller\\AdminBaseController.java");
    BasicFileAttributes basicFileAttributes = null;
    try {
        basicFileAttributes = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
    } catch (IOException e) {
        e.printStackTrace();
    }
    FileTime fileTime = basicFileAttributes.lastModifiedTime();
    long l = fileTime.toMillis();
    Date date = new Date();
    long time = date.getTime();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.MONTH, -2);
    long timeInMillis = calendar.getTimeInMillis();
    System.out.println(time-timeInMillis);
}
    /**
     * 定时上传图片
     * @param path
     * @return
     */
    @Override
    public String timingUpload(String path) {
        File file = new File(path);
        File[] fileList = file.listFiles();
        if(fileList == null || fileList.length<1){
            return "文件夹为空";
        }
        int count = 0;
        int sum = 0;
        StringBuilder allStr = new StringBuilder();
        for (File f1 : fileList) {
        	FileWriter fw = null;
            try{
                // 该文件不是目录则跳过
                if (!f1.isDirectory()) {
                    continue;
                }
                if(f1.listFiles() == null){
                    continue;
                }
                //已读取,跳过
                if(f1.getName().contains("Upload_to_complete")){
                    log.error("文件已经上传过OSS,fileName:{}",f1.getName());
                    // 删除掉一些两个月之前读取过的文件
                    removeDiscardFile(f1);
                    continue;
                }
                sum += f1.listFiles().length;
                int length = 0;
                int repeat = 0;
                StringBuilder str = new StringBuilder();
                // 遍历改文件夹中的文件
                for (File f2 : f1.listFiles()) {
                    // 到第二层文件夹下，则要判断file是否为文件，如果不是则跳过
                    String originalName = f2.getName();
                    if (f2.isDirectory()) {
                        str.append(originalName).append(";");
                        log.info("---------------跳过文件夹--------------------");
                        continue;
                    }
                    log.info("---------------文件名:{}--------------------", originalName);
//                    originalName = originalName.contains("/") ? originalName.substring(originalName.lastIndexOf("/") + 1) : originalName;
//                    if (originalName.contains("/")) {
//                        originalName = originalName.substring(originalName.lastIndexOf("/") + 1);
//                    }
                    //处理文件名称
                    String filename = handleName(originalName);
                    Map<String, String> fileItem = getFileItem(str, originalName, filename);
                    if (fileItem == null){
                        continue;
                    }
                    // 过滤非数字排序
        	        Matcher mZ = Pattern.compile("[0-9]+").matcher(fileItem.get("sort"));
        	        if(!mZ.matches()) {
        	        	str.append(originalName).append(";");
        	        	log.error("---------------文件名格式异常:{}-----------------", filename);
        	        	continue;
        	        }
        	        String lastFix = filename.substring(filename.lastIndexOf("."));
                    String name = UUID.randomUUID().toString().replace("-", "") + lastFix;
                    ProductImage productImage = productImageService.getOne(Wrappers.<ProductImage>lambdaQuery()
                    		//.eq(ProductImage::getUrl, fileItem.get("keyword") + "/" + name)
                    		.eq(ProductImage :: getFolderName, fileItem.get("keyword"))
                    		.eq(ProductImage :: getColor, fileItem.get("color"))
                    		.eq(ProductImage :: getSort, fileItem.get("sort"))
                    		.eq(ProductImage :: getType, fileItem.get("type"))
                    		.last("LIMIT 1")
                            //.eq(ProductImage::getIsFirst, 0)
                            );
//                    if(isExist < 1){
                        // 上传oss
                    	if(StringUtil.isNotBlank(OSSUtil.getVideoType(FilenameUtils.getExtension("." + lastFix)))) {
                    		OSSUtil.uploadLocalVideo(Constants.UPLOAD_FILE_WAREHOUSE_DIR + fileItem.get("keyword") + "/", f2, name);
                    	} else {
                    		// 是否大于2M
                    		boolean size = 2098000 < f2.length() ? true : false;
                    		if(size) {
                    			// 压缩图片
                    			Thumbnails.of(f2).scale(1f).outputQuality(0.35f).toFile(f2); 
                    		}
                    		OSSUtil.uploadLocalImage(Constants.UPLOAD_FILE_WAREHOUSE_DIR + fileItem.get("keyword") + "/", f2, name);
                    	}
                        count++;
                        length++;
                        ProductImageEnum productImageEnum = ProductImageEnum.valueOfByName(fileItem.get("type"));
                        productImage = Objects.isNull(productImage) ? new ProductImage() : productImage;
                        productImage.setFolderName(fileItem.get("keyword"))
                                .setColor(fileItem.get("color"))
                                .setSort(fileItem.get("sort"))
                                .setType(productImageEnum)
                                .setTypeSort(productImageEnum.getSort())
                                .setIsPublic(productImageEnum.getType())
                                .setIsFirst(0)
                                .setUrl(fileItem.get("keyword") + "/" + name);
                        productImageService.saveOrUpdate(productImage);
//                    } else {
//                        repeat++;
//                    }
				}
				File fileText = new File(path + "/" + f1.getName() + "_Upload_to_complete" + DateUtil.nowDateTimeStr() + ".txt");
				file.createNewFile();
				allStr.append(str);
				String text = "-----上传文件总数:" + f1.listFiles().length + ",上传成功" + length + "条;重复" + repeat + "条;---------" + (StringUtils.isBlank(str) ? "" : "失败文件名称:" + str.toString());
				fw = new FileWriter(fileText, true);
				fw.write(text);
				fw.flush();
				fw.close();
                //修改文件夹名称
                f1.renameTo(new File(path + "/" + f1.getName() + "_Upload_to_complete_" + DateUtil.nowDateTimeStr()));
            } catch (Exception e){
                e.printStackTrace();
            } finally {
            	if (fw != null) {
                    try {
                        fw.close();
                    } catch (Exception e2) {
                    }
                }
            }
        }
        
        log.info("-----上传文件总数:{},上传成功{}条;{}---------",sum,count,(StringUtils.isBlank(allStr) ? "" : "失败文件名称:"+allStr.toString()));
        return "上传文件总数:" + sum + ",上传成功:" + count + "条;" + (StringUtils.isBlank(allStr) ? "" : "失败文件名称:"+allStr.toString());
    }

    private void removeDiscardFile(File file) {
        Path filePath = file.toPath();
        BasicFileAttributes basicFileAttributes = null;
        try {
            basicFileAttributes = Files.readAttributes(filePath, BasicFileAttributes.class);
            if (null == basicFileAttributes){
                return;
            }
            FileTime fileTime = basicFileAttributes.lastModifiedTime();
            long mdfLong = fileTime.toMillis();
            Date date = new Date();
            long time = date.getTime();
            if (time - mdfLong < 5270400000L){
                return;
            }
            log.error("两个月前的文件删除: {}",file.getName());
            File[] files = file.listFiles();
            if (null == files || files.length == 0){
                return;
            }
//            for (File file1 : files) {
//                boolean delete = file1.delete();
//                if (delete){
//                    log.error("垃圾文件已经删除: {}",file1.getName());
//                }
//            }
//            boolean delete = file.delete();
//            if (delete){
//                log.error("垃圾文件夹已经删除: {}",file.getName());
//            }
        } catch (IOException e) {
            log.error("filePath: {}, 获取文件参数信息异常: ",filePath,e);
        }
    }

    /**
     * 处理文件名称
     * @param originalName
     * @return
     */
    public String handleName(String originalName) {
        //去空格
        String filename = originalName.replaceAll(" ", "");
        filename = filename.replaceAll("～", "~").replaceAll("（", "(").replaceAll("）", ")").replaceAll("~~","~");
        return filename;
    }

    /**
     * 字段拆分
     * @author daigb
     * @date:  2022-03-28 13:42
     */
    public Map<String, String> getFileItem(StringBuilder str, String originalName, String filename) {
        if (!(filename.contains("~") && filename.contains("(") && filename.contains(")"))) {
            log.error("---------------文件名格式异常:{}-----------------", filename);
            str.append(originalName).append(";");
            return null;
        }
        Map<String, String> fileItem = new HashMap<>();
        String[] split = filename.split("~");
		if (split.length == 4) {
			fileItem.put("keyword", split[0]);
			fileItem.put("color", split[1]);
			fileItem.put("name", split[2]);
			fileItem.put("type", split[3].substring(0, split[3].indexOf("(")));
			fileItem.put("sort", split[3].substring(split[3].lastIndexOf("(") + 1, split[3].lastIndexOf(")")));
        } else {
            log.error("---------------文件名格式异常:{}-----------------", filename);
            str.append(originalName).append(";");
            return null;
        }
        return fileItem;
    }

}

